﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WcfGeebaServer.ContentManage;
using WcfGeebaServer.Users;
using WcfGeebaServer.Policies;
using WcfGeebaServer.DBDAL;
using System.Threading;

namespace TestGeeba
{
    /// <summary>
    /// This is a test class for GForum and is intended
    /// to contain all GForum Unit Tests
    /// </summary>
    [TestClass]
    public class GSubForumTest
    {
        public GSubForumTest()
        {
            Data.ClearDB();
            testedForum = GForum.GetForum();
            moderator = new Member("Moderator", "1234", true);
            testedForum.register("Moderator", "1234");
            testedForum.init(moderator, new GPolicy());
            testedSubForum = new GSubForum("Test");
            testedForum.addSubForum("Test", moderator);
        }

        private GForum testedForum;
        private GSubForum testedSubForum;
        private Member moderator;
        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        public GSubForum TestedSubForum
        {
            get
            {
                return testedSubForum;
            }
            set
            {
                testedSubForum = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        [TestMethod]
        public void EqualsTest()
        {
            GSubForum sf1 = new GSubForum("Topic");
            GSubForum sf2 = new GSubForum("Topic");
            GSubForum sf3 = new GSubForum("Other Topic");
            Assert.IsTrue(sf1.Equals(sf2));
            Assert.IsFalse(sf1.Equals(sf3));
            Assert.IsFalse(sf2.Equals(sf3));
        }

        [TestMethod]
        public void getThreadsTest()
        {
            int count = 0;
            if (testedSubForum.getThreads() != null)
                count = testedSubForum.getThreads().Count;
            Member member = new Member("MsDude", "password", true);
            testedForum.register("MsDude", "password");
            GThread t1 = new GThread("aSubjectForTesting", "bla", member);
            GThread t2 = new GThread("aSubjectForTesting2", "bla", member);
            int id = testedSubForum.publish(t1);
            t1 = testedSubForum.GetThread(id);
            id = testedSubForum.publish(t2);
            t2 = testedSubForum.GetThread(id);
            Assert.IsTrue(testedSubForum.getThreads().Count == count + 2);
            Assert.IsTrue(testedSubForum.getThreads().Contains(t1));
            Assert.IsTrue(testedSubForum.getThreads().Contains(t2));
            Assert.IsFalse(testedSubForum.getThreads().Contains(new GThread("aNonExistingTopic", "bla", member)));
        }

        [TestMethod]
        public void publishTest()
        {
            int count = 0;
            if (testedSubForum.getThreads() != null)
                count = testedSubForum.getThreads().Count;
            int threadID1 = testedSubForum.publish(new GThread("Subject123", "Content", moderator));
            Assert.IsTrue(testedSubForum.getThreads().Count == count + 1);
            int threadID2 = testedSubForum.publish(new GThread("Subject2123", "Content2", moderator));
            Assert.IsTrue(testedSubForum.getThreads().Count == count + 2);
            Assert.IsTrue(threadID1 != threadID2);
        }

        [TestMethod]
        public void addMemberAsModeratorTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator11", "1234", true);
            testedForum.register("moderator11", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic" + i + 5, "conten" + i + 5, m1));
            testedSubForum.addMemberAsModerator(m1);
            Member m2 = new Member("moderator22", "1234", true);
            testedForum.register("moderator22", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic" + i, "conten" + i, m2));
            testedSubForum.addMemberAsModerator(m2);
            Assert.IsTrue(testedSubForum.getModerators().Count == count + 2);
        }

        [TestMethod]
        public void removeMemberFromModeratorsTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator111", "1234", true);
            testedForum.register("moderator111", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic1" + i + 5, "conten1" + i + 5, m1));
            testedSubForum.addMemberAsModerator(m1);
            Member m2 = new Member("moderator221", "1234", true);
            testedForum.register("moderator221", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic1" + i, "conten1" + i, m2));
            testedSubForum.addMemberAsModerator(m2);
            Assert.IsTrue(testedSubForum.getModerators().Count == count + 2);

            Assert.IsFalse(testedSubForum.removeMemberFromModerators(m2));
            Assert.IsFalse(testedSubForum.removeMemberFromModerators(m1));

        }

        [TestMethod]
        public void getModeratorsTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator11111", "1234", true);
            testedForum.register("moderator11111", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic11" + i + 5, "conten11" + i + 5, m1));
            testedSubForum.addMemberAsModerator(m1);
            Member m2 = new Member("moderator221", "1234", true);
            testedForum.register("moderator221", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic11" + i, "conten11" + i, m2));
            testedSubForum.addMemberAsModerator(m2);
            Assert.IsTrue(testedSubForum.getModerators().Count == count + 2);
            Assert.IsTrue(testedSubForum.ContainsModerator(m1));
            Assert.IsTrue(testedSubForum.ContainsModerator(m2));
        }

        [TestMethod]
        public void ContainsModeratorTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator111112", "1234", true);
            testedForum.register("moderator111112", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic121" + i + 5, "conten121" + i + 5, m1));
            testedSubForum.addMemberAsModerator(m1);
            Member m2 = new Member("moderator221", "1234", true);
            testedForum.register("moderator221", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic121" + i, "conten121" + i, m2));
            testedSubForum.addMemberAsModerator(m2);
            Assert.IsTrue(testedSubForum.getModerators().Count == count + 2);
            Assert.IsTrue(testedSubForum.ContainsModerator(m1));
            Assert.IsTrue(testedSubForum.ContainsModerator(m2));
        }

        [TestMethod]
        public void RemoveThreadTest()
        {
            int count = 0;
            if (testedSubForum.getThreads() != null)
                count = testedSubForum.getThreads().Count;
            int threadID1 = testedSubForum.publish(new GThread("Subject1231", "Content", moderator));
            Assert.IsTrue(testedSubForum.getThreads().Count == count + 1);
            int threadID2 = testedSubForum.publish(new GThread("Subject21231", "Content2", moderator));
            Assert.IsTrue(testedSubForum.getThreads().Count == count + 2);
            Assert.IsTrue(threadID1 != threadID2);
            Assert.IsTrue(testedSubForum.RemoveThread(threadID1));
            Assert.IsFalse(testedSubForum.RemoveThread(threadID1));
            Assert.IsTrue(testedSubForum.RemoveThread(threadID2));
        }

        [TestMethod]
        public void RemoveThreadWithCommentTest()
        {
            int count = 0;
            if (testedSubForum.getThreads() != null)
                count = testedSubForum.getThreads().Count;
            int threadID1 = testedSubForum.publish(new GThread("Subject1231", "Content", moderator));
            GThread thread = testedSubForum.GetThread(threadID1);
            thread.addPost(new GPost("subject", "content", moderator, thread));

            Assert.IsTrue(testedSubForum.getThreads().Count == count + 1);
            Assert.IsTrue(testedSubForum.RemoveThread(thread));
            Assert.IsTrue(testedSubForum.getThreads().Count == count);
        }

        [TestMethod]
        public void ReplaceModeratorTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator1199", "1234", true);
            testedForum.register("moderator1199", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic9" + i + 5, "conten9" + i + 5, m1));
            testedSubForum.addMemberAsModerator(m1);
            Member m2 = new Member("moderator2299", "1234", true);
            testedForum.register("moderator2299", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic9" + i, "conten9" + i, m2));
            //TODO: how to change system time??
            /*Assert.IsTrue(testedSubForum.ReplaceModerator(m1, m2));
            Member m3 = new Member("moderator3399", "1234", true);
            Assert.IsFalse(testedSubForum.ReplaceModerator(m2, m3));
            */
            Assert.IsTrue(true);
        }

        [TestMethod]
        public void GetThreadCountTest()
        {
            int count = 0;
            if (testedSubForum.getThreads() != null)
                count = testedSubForum.getThreads().Count;
            for (int i = 0; i < 5; i++)
            {
                testedSubForum.publish(new GThread("1", "1", moderator));
            }
            Assert.IsTrue(testedSubForum.GetThreadCount() == count + 5);
            for (int i = 0; i < 5; i++)
            {
                testedSubForum.publish(new GThread("1", "1", moderator));
            }
            Assert.IsTrue(testedSubForum.GetThreadCount() == count + 10);
        }

        [TestMethod]
        public void GetThreadTest()
        {
            string subject1 = "Subject123";
            string subject2 = "Subject12345";
            string content1 = "someCrazyContent";
            string content2 = "someCrazyContent12345";
            int threadID1 = testedSubForum.publish(new GThread(subject1, content1, moderator));
            int threadID2 = testedSubForum.publish(new GThread(subject2, content2, moderator));
            Assert.IsTrue(testedSubForum.GetThread(threadID1).Subject.Equals(subject1));
            Assert.IsTrue(testedSubForum.GetThread(threadID2).Subject.Equals(subject2));
            Assert.IsTrue(testedSubForum.GetThread(threadID1).Content.Equals(content1));
            Assert.IsTrue(testedSubForum.GetThread(threadID2).Content.Equals(content2));
        }

        [TestMethod]
        public void IsModeratorTest()
        {
            int count = 0;
            if (testedSubForum.getModerators() != null)
                count = testedSubForum.getModerators().Count;
            Member m1 = new Member("moderator119911", "1234", true);
            testedForum.register("moderator119911", "1234");
            for (int i = 0; i < 5; i++)
                testedSubForum.publish(new GThread("topic9" + i + 5, "conten9" + i + 5, m1));
            Assert.IsTrue(testedSubForum.addMemberAsModerator(m1));
            Assert.IsTrue(testedSubForum.IsModerator(m1.Username));
        }

        [TestMethod]
        public void GetLastMessageTest()
        {
            int threadID1 = testedSubForum.publish(new GThread("Subject123", "Content", moderator));
            Thread.Sleep(60);
            int threadID2 = testedSubForum.publish(new GThread("Subject2123", "Content2", moderator));
            Assert.IsTrue(testedSubForum.GetLastMessage(moderator).Id == threadID2);

        }
    }
}
